﻿using Basic.HrDAL.Model;
using Basic.HrModel.DB;
using Basic.HrModel.Msg;
using Basic.HrRemoteModel;
using Basic.HrRemoteModel.Msg.Model;
using SqlSugar;
using WeDonekRpc.Helper;
using WeDonekRpc.Helper.IdGenerator;
using WeDonekRpc.Model;
using WeDonekRpc.SqlSugar;

namespace Basic.HrDAL.Repository
{
    internal class EmpMsgListDAL : BasicDAL<DBEmpMsgList, long>, IEmpMsgListDAL
    {
        public EmpMsgListDAL ( IRepository<DBEmpMsgList> basicDAL ) : base(basicDAL)
        {
        }
        public Result[] Gets<Result> ( MsgGetArg param ) where Result : class, new()
        {
            return this._BasicDAL.Gets<Result>(param.ToWhere());
        }
        public Result[] Query<Result> ( MsgQuery query, IBasicPage paging, out int count ) where Result : class
        {
            paging.InitOrderBy("Sort,AddTime", true);
            return this._BasicDAL.Query<Result>(query.ToWhere(), paging, out count);
        }
        public void Adds ( MsgAdd add )
        {
            DateTime now = DateTime.Now;
            HrMsgStatus status = add.MsgType == HrMsgType.待办消息 ? HrMsgStatus.待办 : HrMsgStatus.无;
            DBEmpMsgList[] adds = add.Items.ConvertAll(a => new DBEmpMsgList
            {
                EmpId = a.EmpId,
                LinkPk = a.LinkPk,
                LinkType = add.LinkType,
                MsgType = add.MsgType,
                TimeOut = a.TimeOut,
                Tag = a.Tag,
                AppId = add.AppId,
                Body = a.Body,
                Attrs = a.Attrs,
                Id = IdentityHelper.CreateId(),
                Sort = (short)( ( (int)a.Priority * 1000 ) + a.Sort.GetValueOrDefault(0) ),
                FormEmpId = a.FormEmpId,
                MsgTitle = a.MsgTitle,
                Priority = a.Priority,
                MsgStatus = status,
                IsRead = false,
                MsgClassify = add.MsgClassify,
                AddTime = now,
            });
            this._BasicDAL.Insert(adds);
        }
        public void Adds ( MsgAdd[] adds )
        {
            List<DBEmpMsgList> list = this._Format(adds);
            this._BasicDAL.Insert(list);
        }
        private List<DBEmpMsgList> _Format ( MsgAdd[] adds )
        {
            DateTime now = DateTime.Now;
            List<DBEmpMsgList> list = new List<DBEmpMsgList>();
            adds.ForEach(c =>
            {
                HrMsgStatus status = c.MsgType == HrMsgType.待办消息 ? HrMsgStatus.待办 : HrMsgStatus.无;
                c.Items.ForEach(a =>
                {
                    list.Add(new DBEmpMsgList
                    {
                        EmpId = a.EmpId,
                        LinkPk = a.LinkPk,
                        LinkType = c.LinkType,
                        MsgType = c.MsgType,
                        TimeOut = a.TimeOut,
                        Tag = a.Tag,
                        AppId = c.AppId,
                        Body = a.Body,
                        Attrs = a.Attrs,
                        Id = IdentityHelper.CreateId(),
                        Sort = (short)( ( (int)a.Priority * 1000 ) + a.Sort.GetValueOrDefault(0) ),
                        FormEmpId = a.FormEmpId,
                        MsgTitle = a.MsgTitle,
                        Priority = a.Priority,
                        MsgStatus = status,
                        IsRead = false,
                        MsgClassify = c.MsgClassify,
                        AddTime = now,
                    });
                });
            });
            return list;
        }
        public void SetAlreadyRead ( long id )
        {
            if ( !this._BasicDAL.Update(new DBEmpMsgList
            {
                Id = id,
                IsRead = true,
                ReadTime = DateTime.Now,
            }, new string[]
            {
                "IsRead",
                "ReadTime"
            }) )
            {
                throw new ErrorException("hr.msg.status.set.fail");
            }
        }
        public void SetAlreadyRead ( long[] ids )
        {
            DateTime now = DateTime.Now;
            if ( !this._BasicDAL.Update(ids.ConvertAll(a => new DBEmpMsgList
            {
                Id = a,
                IsRead = true,
                ReadTime = now
            }), new string[]
            {
                "IsRead",
                "ReadTime"
            }) )
            {
                throw new ErrorException("hr.msg.status.set.fail");
            }
        }
        public void SetAlreadyDo ( long id )
        {
            if ( !this._BasicDAL.Update(new DBEmpMsgList
            {
                Id = id,
                MsgStatus = HrMsgStatus.已办,
                DoneTime = DateTime.Now,
            }, new string[]
            {
                "MsgStatus",
                "DoneTime"
            }) )
            {
                throw new ErrorException("hr.msg.status.set.fail");
            }
        }
        public long[] GetMsgId ( MsgItem[] items )
        {
            if ( items.Length == 1 )
            {
                MsgItem item = items[0];
                if ( item.Tag.IsNull() )
                {
                    return this._BasicDAL.Gets(a => a.LinkType == item.LinkType && a.LinkPk == item.LinkPk && a.ToVoid == false, a => a.Id);
                }
                return this._BasicDAL.Gets(a => a.LinkType == item.LinkType && a.LinkPk == item.LinkPk && a.Tag == item.Tag && a.ToVoid == false, a => a.Id);
            }
            ISugarQueryable<MsgId>[] tables = items.ConvertAll(c =>
            {
                if ( c.Tag.IsNull() )
                {
                    return this._BasicDAL.Queryable.Where(a => a.LinkType == c.LinkType && a.LinkPk == c.LinkPk && a.ToVoid == false).Select(a => new MsgId
                    {
                        Id = a.Id,
                    });
                }
                return this._BasicDAL.Queryable.Where(a => a.LinkType == c.LinkType && a.LinkPk == c.LinkPk && a.Tag == c.Tag && a.ToVoid == false).Select(a => new MsgId
                {
                    Id = a.Id,
                });
            });
            return this._BasicDAL.Provider.Union(tables).Select(a => a.Id).ToArray();
        }
        public long[] GetWaitToVoidMsgId ( ToVoidItem[] items )
        {
            if ( items.Length == 1 )
            {
                ToVoidItem item = items[0];
                if ( item.Tag.IsNull() )
                {
                    return this._BasicDAL.Gets(a => a.LinkType == item.LinkType && item.LinkPk.Contains(a.LinkPk) && a.ToVoid == false, a => a.Id);
                }
                return this._BasicDAL.Gets(a => a.LinkType == item.LinkType && item.LinkPk.Contains(a.LinkPk) && a.Tag == item.Tag && a.ToVoid == false, a => a.Id);
            }
            ISugarQueryable<MsgId>[] tables = items.ConvertAll(c =>
            {
                if ( c.Tag.IsNull() )
                {
                    return this._BasicDAL.Queryable.Where(a => a.LinkType == c.LinkType && c.LinkPk.Contains(a.LinkPk) && a.ToVoid == false).Select(a => new MsgId
                    {
                        Id = a.Id,
                    });
                }
                return this._BasicDAL.Queryable.Where(a => a.LinkType == c.LinkType && c.LinkPk.Contains(a.LinkPk) && a.Tag == c.Tag && a.ToVoid == false).Select(a => new MsgId
                {
                    Id = a.Id,
                });
            });
            return this._BasicDAL.Provider.Union(tables).Select(a => a.Id).ToArray();
        }

        public void ToVoidMsg ( long[] msgId )
        {
            if ( !this._BasicDAL.Update(a => a.ToVoid == true, a => msgId.Contains(a.Id) && a.ToVoid == false) )
            {
                throw new ErrorException("hr.msg.status.set.fail");
            }
        }
        public void ToVoidMsg ( long msgId )
        {
            if ( !this._BasicDAL.Update(a => a.ToVoid == true, a => a.Id == msgId && a.ToVoid == false) )
            {
                throw new ErrorException("hr.msg.status.set.fail");
            }
        }

        public void Save ( BatchOpt opt )
        {
            ISqlQueue<DBEmpMsgList> queue = this._BasicDAL.BeginQueue();
            if ( !opt.Adds.IsNull() )
            {
                List<DBEmpMsgList> list = this._Format(opt.Adds);
                queue.Insert(list);
            }
            if ( !opt.ToVoidId.IsNull() )
            {
                queue.UpdateOneColumn(a => a.ToVoid == true, a => opt.ToVoidId.Contains(a.Id) && a.ToVoid == false);
            }
            if ( !opt.DoneId.IsNull() )
            {
                DateTime now = DateTime.Now;
                queue.Update(a => new DBEmpMsgList
                {
                    MsgStatus = HrMsgStatus.已办,
                    DoneTime = now,
                }, a => opt.DoneId.Contains(a.Id));
            }
            _ = queue.Submit();
        }

        public Dictionary<string, int> GetMsgTotal ( MsgGetArg arg )
        {
            return this._BasicDAL.GroupBy(arg.ToWhere(), a => a.MsgClassify, a => new
            {
                a.MsgClassify,
                num = SqlFunc.AggregateCount(a.Id)
            }).ToDictionary(a => a.MsgClassify, a => a.num);
        }
    }
}
